package com.zombie.logic.level;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.w3c.dom.Node;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.tiled.SimpleTileAtlas;
import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;
import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader;
import com.badlogic.gdx.graphics.g2d.tiled.TiledMap;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Disposable;
import com.zombie.Constants;
import com.zombie.logic.core.ZombieWorld;
import com.zombie.logic.item.Item;
import com.zombie.logic.level.wave.Spawn;
import com.zombie.logic.level.wave.Wave;
import com.zombie.logic.object.ItemObject;
import com.zombie.logic.object.StaticObject;

public class Level implements Disposable{

	public int 						id = 0;
	public String 					name = "Abandoned City";
	public Map<Integer,Wave> 		waves = new HashMap<Integer,Wave>();
	public Map<Integer,SpawnPoint> 	spawnPoints = new HashMap<Integer,SpawnPoint>();
	public Map<Integer,MobDef> 		mobs = new HashMap<Integer,MobDef>();
	public List<RandomItemSpawn> 	itemRandomSpawnPoints = new ArrayList<RandomItemSpawn>();
	public TiledMap 				tiledMap;
	public TileAtlas 				tileAtlas;
	public String 					icon;
	public int 						backgroundCount;
	


	public static void loadLevel(Node node) {
		Level level = new Level();
		level.icon = node.getAttributes().getNamedItem("icon").getNodeValue();
		for(int i = 0; i < node.getChildNodes().getLength();i++ ){
			Node n = node.getChildNodes().item(i);
			if (n.getNodeName().equalsIgnoreCase("poly")) {
				Vector<Vector2> points = new Vector<Vector2>();
				for(int e = 0; e < n.getChildNodes().getLength();e++ ) {
					Node child = n.getChildNodes().item(e);
					if (child.getNodeName().equalsIgnoreCase("point")) {
						float x = Integer.parseInt(child.getAttributes().getNamedItem("x").getNodeValue());
						float y = Integer.parseInt(child.getAttributes().getNamedItem("y").getNodeValue());		
						points.add(new Vector2(x,y));
					}
				}
			} else if (n.getNodeName().equalsIgnoreCase("box")) {
				float x,y,w,h;
				x = Float.parseFloat(n.getAttributes().getNamedItem("x").getNodeValue());
				y = Float.parseFloat(n.getAttributes().getNamedItem("y").getNodeValue());
				w = Float.parseFloat(n.getAttributes().getNamedItem("w").getNodeValue());
				h = Float.parseFloat(n.getAttributes().getNamedItem("h").getNodeValue());
				if (n.getAttributes().getNamedItem("tiled")!= null){
					x*=Constants.TILESIZE;
					y*=Constants.TILESIZE;
					w*=Constants.TILESIZE;
					h*=Constants.TILESIZE;
				}
//				x-=14;
//				y+=14;
//				w-=4;
//				h-=4;
				ZombieWorld.createStaticBox(x+w/2,y+h/2,w,h);
			} else if (n.getNodeName().equalsIgnoreCase("start")) {
				float x,y;
				x = Float.parseFloat(n.getAttributes().getNamedItem("x").getNodeValue());
				y = Float.parseFloat(n.getAttributes().getNamedItem("y").getNodeValue());
				if (n.getAttributes().getNamedItem("tiled")!= null){
					x*=Constants.TILESIZE;
					y*=Constants.TILESIZE;
				}
				Constants.START_X = x;
				Constants.START_Y = y;	
			} else if (n.getNodeName().equalsIgnoreCase("starttext")) {
//	FIXME		Text text = new Text(ResourceManager.getText(n.getAttributes().getNamedItem("resource").getNodeValue()));
//				text.startAt = Long.parseLong(n.getAttributes().getNamedItem("startat").getNodeValue());
//				Constants.START_TEXT.add(text);
			} else if (n.getNodeName().equalsIgnoreCase("waves")) {
				 loadWaves(n,level);
			} else if (n.getNodeName().equalsIgnoreCase("object")){
				loadObject(n,level);
			} else if (n.getNodeName().equalsIgnoreCase("itemSpawn")){
				loadItemSpawn(n,level);
			} else if (n.getNodeName().equalsIgnoreCase("randomSpawn")){
				loadRandomItemSpawn(n,level);
			} else if (n.getNodeName().equalsIgnoreCase("map")){
				level.tiledMap = TiledLoader.createMap(Gdx.files.internal("data/level/"+n.getAttributes().getNamedItem("resource").getNodeValue()));
				level.tileAtlas =  new SimpleTileAtlas(level.tiledMap,Gdx.files.internal("data/level/"));
				level.backgroundCount = Integer.parseInt(n.getAttributes().getNamedItem("backgroundCount").getNodeValue());
			}
		}
		ZombieWorld.level = level;
	}
	
	private static void loadRandomItemSpawn(Node node,Level level) {
		RandomItemSpawn item = new RandomItemSpawn();
		item.id = Integer.parseInt(node.getAttributes().getNamedItem("id").getNodeValue());
		item.timer = Integer.parseInt(node.getAttributes().getNamedItem("timer").getNodeValue());
		item.chance = Integer.parseInt(node.getAttributes().getNamedItem("chance").getNodeValue());
	
		for(int i = 0; i < node.getChildNodes().getLength();i++ ){
			Node n = node.getChildNodes().item(i);
			if (n.getNodeName().equalsIgnoreCase("spawnPoint")){
				SpawnPoint sp = new SpawnPoint();
				sp.id = Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
				sp.minX = Integer.parseInt(n.getAttributes().getNamedItem("minX").getNodeValue());
				sp.maxX = Integer.parseInt(n.getAttributes().getNamedItem("maxX").getNodeValue());
				sp.minY = Integer.parseInt(n.getAttributes().getNamedItem("minY").getNodeValue());
				sp.maxY = Integer.parseInt(n.getAttributes().getNamedItem("maxY").getNodeValue());
				item.spawnPoints.add(sp);
			} else if (n.getNodeName().equalsIgnoreCase("itemId")){
				Item it = Item.getItemById(Integer.parseInt(n.getTextContent()));
				item.drop.add(it);
			}
		}
		level.itemRandomSpawnPoints.add(item);
		item.init();
	}
	
	private static void loadItemSpawn(Node n, Level level) {
		float x,y;
		x = Float.parseFloat(n.getAttributes().getNamedItem("x").getNodeValue());
		y = Float.parseFloat(n.getAttributes().getNamedItem("y").getNodeValue());
		if (n.getAttributes().getNamedItem("tiled")!= null){
			x*=Constants.TILESIZE;
			y*=Constants.TILESIZE;
		}
		int id = Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
		ItemObject obj = new ItemObject(x, y,Item.getItemById(id));
		ZombieWorld.addObject(obj);
	}
	
	private static void loadObject(Node n, Level level) {
		float x,y,density;
		x = Float.parseFloat(n.getAttributes().getNamedItem("x").getNodeValue());
		y = Float.parseFloat(n.getAttributes().getNamedItem("y").getNodeValue());
		String type = n.getAttributes().getNamedItem("type").getNodeValue();
		density = Float.parseFloat(n.getAttributes().getNamedItem("density").getNodeValue());
		if (n.getAttributes().getNamedItem("tiled")!= null){
			x*=Constants.TILESIZE;
			y*=Constants.TILESIZE;
		}
		StaticObject obj = new StaticObject(x,y);
		obj.image = n.getAttributes().getNamedItem("image").getNodeValue();
		obj.material = n.getAttributes().getNamedItem("material").getNodeValue();
		obj.angle = Float.parseFloat(n.getAttributes().getNamedItem("angle").getNodeValue());
		if (n.getAttributes().getNamedItem("geom").getNodeValue().equalsIgnoreCase("box")){
			obj.size.x = Float.parseFloat(n.getAttributes().getNamedItem("w").getNodeValue());
			obj.size.y = Float.parseFloat(n.getAttributes().getNamedItem("h").getNodeValue());
			if (type.equalsIgnoreCase("dynamic"))
				obj.body = ZombieWorld.createDynamicBox(x,y,obj.size.x,obj.size.y,obj.angle,density, false, 10f);
			else
				obj.body = ZombieWorld.createStaticBox(x,y,obj.size.x,obj.size.y,obj.angle);
		} else if  (n.getAttributes().getNamedItem("geom").getNodeValue().equalsIgnoreCase("circle")){
			float radius = Float.parseFloat(n.getAttributes().getNamedItem("radius").getNodeValue());
			obj.size.x = radius*2;
			obj.size.y = radius*2;
			if (type.equalsIgnoreCase("dynamic"))
				obj.body = ZombieWorld.createDynamicCircle(x,y,radius,obj.angle,density,false, 10f);
		}
		obj.body.setUserData(obj);
		obj.checkLife();
		ZombieWorld.addObject(obj);
	}
	
	private static void loadWaves(Node n, Level level) {
		for(int i = 0; i < n.getChildNodes().getLength();i++ ){
			Node node = n.getChildNodes().item(i);
			if (node.getNodeName().equalsIgnoreCase("wave")) {
				Wave w = new Wave();
				w.id =  Integer.parseInt(node.getAttributes().getNamedItem("id").getNodeValue());
				w.owner = level;
				loadSpawns(w,node);
				level.waves.put(w.id, w);
			} else if (node.getNodeName().equalsIgnoreCase("spawnPoint")){
				loadSpawnPoints(level,node);
			} else if (node.getNodeName().equalsIgnoreCase("mob")){
				loadMobs(level,node);
			}
		}
	}
	
	private static void loadSpawns(Wave w, Node node) {
		for(int i = 0; i < node.getChildNodes().getLength();i++ ){
			Node n = node.getChildNodes().item(i);
			if (n.getNodeName().equalsIgnoreCase("spawn")){
				Spawn sp = new Spawn();
				sp.id = Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
				sp.time = Integer.parseInt(n.getAttributes().getNamedItem("time").getNodeValue());
				sp.mobId = Integer.parseInt(n.getAttributes().getNamedItem("mobId").getNodeValue());
				sp.spawnPoint = Integer.parseInt(n.getAttributes().getNamedItem("spawnPoint").getNodeValue());
				sp.count = Integer.parseInt(n.getAttributes().getNamedItem("count").getNodeValue());
				w.spawns.put(sp.id, sp);
			}
		}
	}
	
	private static void loadMobs(Level level, Node n) {
		MobDef mob = new MobDef();
		mob.id = Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
		mob.name = n.getAttributes().getNamedItem("name").getNodeValue();
		mob.image = n.getAttributes().getNamedItem("image").getNodeValue();
		mob.className = n.getAttributes().getNamedItem("class").getNodeValue();
		
		if (n.getAttributes().getNamedItem("size") != null){
			String[] size = n.getAttributes().getNamedItem("size").getNodeValue().split(":");
			mob.width = Integer.parseInt(size[0]);	
			mob.height = Integer.parseInt(size[1]);
		}
		mob.level = Integer.parseInt(n.getAttributes().getNamedItem("lvl").getNodeValue());
		String[] hps = n.getAttributes().getNamedItem("hp").getNodeValue().split(":");
		mob.minHp = Integer.parseInt(hps[0]);
		mob.maxHp = Integer.parseInt(hps[1]);
		String[] dmgs = n.getAttributes().getNamedItem("damage").getNodeValue().split(":");
		mob.minDamage = Integer.parseInt(dmgs[0]);
		mob.maxDamage = Integer.parseInt(dmgs[1]);
		String[] vels = n.getAttributes().getNamedItem("velocity").getNodeValue().split(":");
		mob.minVelocity= Float.parseFloat(vels[0]);
		mob.maxVelocity = Float.parseFloat(vels[1]);
		
		if (n.getAttributes().getNamedItem("defence") != null)
			mob.defence = Integer.parseInt(n.getAttributes().getNamedItem("defence").getNodeValue());	
		if (n.getAttributes().getNamedItem("evasion") != null)
			mob.evasion = Float.parseFloat(n.getAttributes().getNamedItem("evasion").getNodeValue());
		level.mobs.put(mob.id, mob);
	}
	
	private static void loadSpawnPoints(Level level, Node n) {
		SpawnPoint sp = new SpawnPoint();
		sp.id = Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
		sp.minX = Integer.parseInt(n.getAttributes().getNamedItem("minX").getNodeValue());
		sp.maxX = Integer.parseInt(n.getAttributes().getNamedItem("maxX").getNodeValue());
		sp.minY = Integer.parseInt(n.getAttributes().getNamedItem("minY").getNodeValue());
		sp.maxY = Integer.parseInt(n.getAttributes().getNamedItem("maxY").getNodeValue());
		level.spawnPoints.put(sp.id, sp);
	}

	@Override
	public void dispose() {
		tileAtlas.dispose();
		tileAtlas = null;
		
	}

}
